import log from '../../../helpers/logger';
import { pushDiscordWebhook } from '../../../helpers/pushDiscordWebhook';
//import { validateLink } from '../../../helpers/dataValidation';

import {
  authorizedRouteHandler,
  ControllerMethodTypes,
  defaultRouteHandler,
} from '../../../../interfaces';
import {
  getAllUsers,
  getAllUserGroups,
  getAllUserGroupLinks,
  getAllUsersWithGroups, getUserById, saveImageurlToDatabase, AuthProvider
} from '../../../services/uctoo/uctoo_user';
import fs from 'fs';
import { hideSelectedObjectKeys } from '../../../helpers/utilsJS';
import { Request } from 'hyper-express';
import { showSelectedObjectKeys } from '../../../helpers/utilsJS';
import { uctoo_user } from '../../../../../prisma/generated/uctoo';
import { setExCache } from '../../../helpers/redis';
import * as bcrypt from 'bcryptjs';
import { PrismaClient } from '../../../../../prisma/generated/uctoo'

const db = new PrismaClient({
  log: ['query', 'info', 'warn', 'error'],
});

const { API_URL } = process.env;
  //#region AutoCreateCode
import {
  createUctooUser,
  deleteUctooUserFromDatabase,
  deleteMultiUctooUserFromDatabase,
  editUctooUserInDatabase,
  editMultiUctooUserInDatabase,
  getUctooUserFromDatabase,
  getUctooUsersFromDatabase,
  queryUctooUsersFromDatabase,
  countUctooUsers
} from '../../../services/uctoo/uctoo_user';

class uctooUctooUserController {

  protected validateAndDestructureBody = async (
    req: Request,
    userId: string,
    actionType: ControllerMethodTypes
  ) => {
    const body = await req.json();
    const keysArray = Object.keys(body);       //如需自定义控制接收字段可在此定义，如['id','link','privacy_level','owner','description','group_id','stars'] ，默认接收所有提交字段
    const uctooUctooUser = showSelectedObjectKeys(body, keysArray) as uctoo_user;
    uctooUctooUser.creator = userId;

    return uctooUctooUser;
  };
  public add: authorizedRouteHandler = async (req, res) => {
    try {
      const user = res.locals.id.user;
      const uctooUctooUser = await this.validateAndDestructureBody(
        req,
        user,
        ControllerMethodTypes.ADD
      );
      if (!uctooUctooUser) return res.status(400).json({ errno: "40001", errmsg: '提交数据格式错误' });

      const createdUctooUser = await createUctooUser(uctooUctooUser);
      if (!createdUctooUser) return res.status(500).json({ errno: "50001", errmsg: "database query failed" });

      res.status(200).json(createdUctooUser);
    } catch (e) {
      log.error({ errno: "50000", errmsg: e.message, desc: e });
      return res.status(500).json({ errno: "50000", errmsg: e.message });
    }
  };
  public edit: authorizedRouteHandler = async (req, res) => {
    try {
      const user = res.locals.id.user;
      const body = await req.json();
      const { id,ids,force } = body;

      if(ids){
        const uctooUctooUser = await this.validateAndDestructureBody(
          req,
          user,
          ControllerMethodTypes.EDIT
        );
        if (!uctooUctooUser) return res.status(400).json({ errno: "40001", errmsg: '提交数据格式错误' });

        const editedUctooUser = await editMultiUctooUserInDatabase(uctooUctooUser, JSON.parse(ids), user);
        
        if (typeof editedUctooUser === 'object' && 'success' in editedUctooUser) {
          if (!editedUctooUser.success) {
            return res.status(403).json({
              errno: "40301", 
              errmsg: editedUctooUser.reason,
              ...(editedUctooUser.uctooUserId && { uctooUserId: editedUctooUser.uctooUserId })
            });
          }
          return res.status(200).json(editedUctooUser.data);
        }
        
        res.status(200).json(editedUctooUser);
      }else{
        const uctooUctooUser = await this.validateAndDestructureBody(
          req,
          user,
          ControllerMethodTypes.EDIT
        );
        if (!uctooUctooUser) return res.status(400).json({ errno: "40001", errmsg: '提交数据格式错误' });

        const editedUctooUser = await editUctooUserInDatabase(uctooUctooUser, uctooUctooUser.id, user);
        
        if (typeof editedUctooUser === 'object' && 'success' in editedUctooUser) {
          if (!editedUctooUser.success) {
            return res.status(403).json({ errno: "40301", errmsg: editedUctooUser.reason });
          }
          return res.status(200).json(editedUctooUser.data);
        }
        res.status(200).json(editedUctooUser);
      }      
    } catch (e) {
      log.error({ errno: "50000", errmsg: e.message, desc: e });
      return res.status(500).json({ errno: "50000", errmsg: e.message });
    }
  };
  public delete: authorizedRouteHandler = async (req, res) => {
    try {
      const body = await req.json();
      const { id,ids,force } = body;
      const user = res.locals.id.user;

      if(ids){
        const deletionResult = await deleteMultiUctooUserFromDatabase(JSON.parse(ids), force, user);
        
        if (typeof deletionResult === 'object' && 'success' in deletionResult) {
          if (!deletionResult.success) {
            return res.status(403).json({
              errno: "40301", 
              errmsg: deletionResult.reason,
              ...(deletionResult.uctooUserId && { uctooUserId: deletionResult.uctooUserId })
            });
          }
          return res.status(200).json({ desc: '删除成功' });
        }
        
      }else{
        const deletionResult = await deleteUctooUserFromDatabase(id, force, user);
        
        if (typeof deletionResult === 'object' && 'success' in deletionResult) {
          if (!deletionResult.success) {
            return res.status(403).json({ errno: "40301", errmsg: deletionResult.reason });
          }
          return res.status(200).json({ desc: '删除成功' });
        }
        
      }

      res.status(200).json({ desc: '删除成功' });
    } catch (e) {
      log.error({ errno: "50000", errmsg: e.message, desc: e });
      return res.status(500).json({ errno: "50000", errmsg: e.message });
    }
  };
  public getSingle: authorizedRouteHandler = async (req, res) => {
    try {
      const { id } = req.params;
      const user = res.locals.id.user;

      const uctooUserFromDb = await getUctooUserFromDatabase(id, user);
      if (!uctooUserFromDb) {
        return res.status(404).json({ 
          errno: "40401", 
          errmsg: '未找到该实体或您没有权限访问' 
        });
      }

      res.status(200).json(uctooUserFromDb);
    } catch (e) {
      log.error({ errno: "50000", errmsg: e.message, desc: e });
      return res.status(500).json({ errno: "50000", errmsg: e.message });
    }
  };
  public getMany: authorizedRouteHandler = async (req, res) => {
    try {
      const limit = parseInt(req.params.limit);
      const page = parseInt(req.params.page) || 0;
      const skip = parseInt(req.params.skip) || 0;
      const query = req.query;
      
      if (limit > 100) return res.status(400).json({ errno: "40002", errmsg: '请求数量不能超过100条' });
      if (isNaN(limit)) return res.status(400).json({ errno: "40003", errmsg: '请求数量必须是数字' });
      
      const user = res.locals.id.user;
      const totalCount = await countUctooUsers(user);
      
      if (query) {
        const uctooUsersFromDb = await queryUctooUsersFromDatabase(limit, page, skip, query, user);
        if (!uctooUsersFromDb) return res.status(404).json({ errno: "40401", errmsg: '未找到符合条件的实体' });

        res.status(200).json({
          currentPage: page,
          totalCount: totalCount,
          totalPage: Math.ceil(Number(totalCount)/limit),
          uctooUsers: uctooUsersFromDb
        });
      } else {
        const uctooUsersFromDb = await getUctooUsersFromDatabase(limit, skip, page, user);
        if (!uctooUsersFromDb) return res.status(404).json({ errno: "40401", errmsg: '未找到符合条件的实体' });

        res.status(200).json({
          currentPage: page,
          totalCount:totalCount,
          totalPage: Math.ceil(Number(totalCount)/limit),
          uctooUsers: uctooUsersFromDb
        });
      }


    } catch (e) {
      log.error({ errno: "50000", errmsg: e.message, desc: e });
      return res.status(500).json({ errno: "50000", errmsg: e.message });
    }
  };
  //#endregion AutoCreateCode
  public handleAllUsers: authorizedRouteHandler = async (req, res) => {
    const users = await getAllUsers();
    return res.status(200).json(users);
  };
  
  public handleAllUsersWithGroups: authorizedRouteHandler = async (req, res) => {
    const users = await getAllUsersWithGroups();
    return res.status(200).json(users);
  };

  public handleUserGroupLinks: authorizedRouteHandler = async (req, res) => {
    const username = req.params.user;
    const group = req.params.group;
    const links = await getAllUserGroupLinks(username, group);
    return res.status(200).json(links);
  };

  public handleAllUsersGroups: authorizedRouteHandler = async (req, res) => {
    const username = req.params.user;
    const userLinkgroups = await getAllUserGroups(username);
    return res.status(200).json(userLinkgroups);
  };

  public handleProfileImageUpload: authorizedRouteHandler = async (request, response) => {
    // Ensure the user is signed in and retrieve their acccount id
    // We use the hyper-express-session middleware here
    // await request.session.start();
    console.log('handleProfileImageUpload:');
    log.info('handleProfileImageUpload');
    const id = response.locals.id;
    console.log(response.locals.id);
    console.log(response.locals);
    const account_id = id.user;  //已登录用户的id即user表id字段
    log.info(account_id);
    if (account_id === undefined) return response.status(403).send('You must be logged in to use this endpoint.');


    // Begin parsing this request as a multipart request
    let save_path;
    let avatar_url;
    try {
      await request.multipart(async (field) => {
        // Ensure that this field is a file-type
        // You may also perform your own checks on the encoding and mime type as needed
        if (field.file) {

          // Save the file to the profile images folder
          const rootDir = process.cwd();
          const fileName = field.name;
          log.info(fileName);
          let dir_path = rootDir + `/assets/${account_id}`;
          save_path = rootDir + `/assets/${account_id}/${fileName}`;
          avatar_url = API_URL + `/assets/${account_id}/${fileName}`;
          if (fs.existsSync(dir_path)) {
            console.log('dir exist');
          } else {
            console.log('dir not exist');
            fs.mkdir(dir_path, { recursive: true }, (err) => {
              if (err) throw err;
              console.log('mkdir success');
            });
          }
          log.info(save_path);
          // Use an await while writing to ensure the "await request.multipart()" does not continue until this file is done writing
          await field.write(save_path);
        }
      });
    } catch (error) {
      log.info(error);
      // The multipart parser may throw a string constant as an error
      // Be sure to handle these as stated in the documentation
      if (typeof error as string === 'FILES_LIMIT_REACHED') {
        return response.status(403).send('You sent too many files! Try again.');
      } else {
        return response.status(500).send('Oops! An uncaught error occured on our end.');
      }
    }

    // Ensure save_path is defined, if it is undefined than that means we did not receive an image.
    if (save_path) {
      // You may do your own post processing on the image here
      const refreshUser = await saveImageurlToDatabase(account_id, avatar_url);

      const wuser = hideSelectedObjectKeys(refreshUser, ['id', 'password']);
      return response.json(wuser);
    } else {
      // We did not receive any image in the multipart request, let the user know
      return response.status(400).send('No profile image was received. Please try again.');
    }
    //return response.status(200).json(userLinkgroups);
  };
}

export default uctooUctooUserController;
